package com.jackstraw.jack_base.datasource.database.parten.entity.bean;

import com.jackstraw.jack_base.datasource.common.factory.DataSourceBuildFactory;
import com.jackstraw.jack_base.datasource.database.parten.entity.DataBaseEntity;
import com.jackstraw.jack_base.datasource.database.parten.entity.enums.DataBaseSchemaTypeEnum;
import com.jackstraw.jack_base.util.SpringUtil;
import com.jackstraw.jack_base.util.entity.DefaultConstants;
import org.springframework.context.support.GenericApplicationContext;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 数据库工厂类
 *
 * @param <DBE>
 */
public abstract class DataBaseFactory<DBE extends DataBaseEntity<DBE>>
        implements DataSourceBuildFactory<DataBaseTemplate<DBE>, DataBasePropertiesEntity<DBE>> {

    /**
     * 写数据源名称
     */
    private final String WRITE_DATASOURCE_NAME = DefaultConstants.DEFAULT_DATA_BASE_MAIN_NAME;

    /**
     * 读数据源名称
     */
    private final String READ_DATASOURCE_NAME = "DATABASE_READ";

    @Override
    public DataBaseTemplate<DBE> build(String tenantName, String dataSourceName, DataBasePropertiesEntity<DBE> propertiesEntity) {

        String beanName = tenantName.concat("_").concat(dataSourceName);

        DataBaseTemplate<DBE> dataBaseTemplate = new DataBaseTemplate<>();

        DataBaseRoutingDataSource dataBaseRoutingDataSource = new DataBaseRoutingDataSource();
        dataBaseRoutingDataSource.setPropertiesEntity(propertiesEntity);
        DBE dataBaseEntity = propertiesEntity.getDataBaseEntity();
        String dataBaseName = beanName.concat("_").concat(WRITE_DATASOURCE_NAME);
        dataBaseEntity.setName(dataBaseName);
        DataSource dataSource = this.dataSource(dataBaseEntity);
        //设置默认的
        dataBaseRoutingDataSource.setDefaultTargetDataSource(dataSource);
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(dataBaseName, dataSource);
        dataBaseRoutingDataSource.setTargetDataSources(targetDataSources);
        dataBaseRoutingDataSource.getWriteDataBaseNameList().add(dataBaseName);

        if (DataBaseSchemaTypeEnum.rw.equals(propertiesEntity.getDataBaseSchemaTypeEnum())) {
            //说明是读写分离
            dataBaseRoutingDataSource.setReadDataBaseNameList(new ArrayList<>());
            AtomicInteger index = new AtomicInteger();
            propertiesEntity.getReadDataBaseEntityList().stream().forEach(readDataBaseEntity -> {
                String readDataBaseName = beanName.concat("_")
                        .concat(READ_DATASOURCE_NAME).concat(String.valueOf(index.getAndIncrement()));
                readDataBaseEntity.setName(readDataBaseName);
                targetDataSources.put(readDataBaseName, this.dataSource(readDataBaseEntity));
                dataBaseRoutingDataSource.getReadDataBaseNameList().add(readDataBaseName);
            });
        }
        dataBaseTemplate.setDataBaseRoutingDataSource(dataBaseRoutingDataSource);
        dataBaseRoutingDataSource.afterPropertiesSet();
        //将DataBaseRoutingDataSource注册到bean容器
        SpringUtil.registerBean(beanName, DataSource.class, () -> dataBaseRoutingDataSource);
        return dataBaseTemplate;
    }

    protected abstract DataSource dataSource(DBE dataBaseEntity);
}
